﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCityPlayer.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-12
//    @Email			:    445267987@qq.com
//    @Module           :    NFCityPlayer
//    @Desc             :
//
// -------------------------------------------------------------------------

#include "NFCityPlayer.h"

#include "NFCityPacketSendUtil.h"
#include "NFCityPlayerUtil.h"
#include "NFCitySession.h"
#include "proto_svr_common.nanopb.h"
#include "proto_svr_map.pb.h"
#include "NFComm/NFCore/NFRandom.hpp"
#include "NFLogicCommon/NFCommMacros.h"

const int DEFAULT_OFFLINE_TIME = 30 * 60;

NFCityPlayer::NFCityPlayer()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFCityPlayer::~NFCityPlayer()
{
}

int NFCityPlayer::CreateInit()
{
    SetObjectType(EN_CITY_WOT_PLAYER);
    m_ullRoleID = 0;
    m_iClientSessionID = 0;
    m_pClientSession = nullptr;

    m_bIsInit = false;
    m_bEnterSvr = false;
    m_iToken = 0;
    m_iTransferID = 0;

    m_ullGuildID = 0;
    m_ullGuildBattleID = 0;
    m_ullDungeonID = 0;
    m_ullRaidUUID = 0;
    m_titleID = 0;
    m_titleItemID = 0;
    m_iTitle2ID = 0;
    m_iWeaponStrengLv = 0;

    for (int i = 0; i < (int)ARRAYSIZE(m_fashions); i++)
    {
        m_fashions[i] = 0;
    }
    m_familyCallerID = 0;
    m_transExpRole = 0;
    m_isPrepare = false;

    m_iFollowPartnerID = 0;
    m_bFollowPartnerfatigue = false;
    m_iFollowPartnerStar = 0;

    SetPlayerStatus(CACHE_STATUS_NONE);
    m_iToken = NFRandInt(1, ONE_MILLION);
    SetTimer(500, 0, 0, 0, 0, 0);

    m_iCurSynSeq = 0;
    m_iLogicSvrId = 0;

    m_bStateLeave = false;
    return 0;
}

int NFCityPlayer::ResumeInit()
{
    m_pClientSession = nullptr;
    return 0;
}

int NFCityPlayer::OnTimer(int timeId, int callCount)
{
    Tick();
    return 0;
}

bool NFCityPlayer::IsCanLogout()
{
    int iLogoutGap = GetBattleExt()->IsInBattle() ? 300 : 60;
    if (m_oTeamExt.IsInTeam(m_ullRoleID))
    {
        if (NF_ADJUST_TIMENOW() - m_lastDisconnectTime >= DEFAULT_OFFLINE_TIME)
        {
            return true;
        }
    }
    else if (NF_ADJUST_TIMENOW() - m_lastDisconnectTime >= (uint64_t)iLogoutGap)
    {
        return true;
    }
    return true;
}

int NFCityPlayer::DoOnline()
{
    LogicTick();
    return 0;
}

bool NFCityPlayer::IsCanDelete()
{
    return true;
}

int NFCityPlayer::DoLogout()
{
    NFCityPlayerUtil::RemovePlayer(this);
    return 0;
}

int NFCityPlayer::Fini()
{
    SynMapData();
    return 0;
}

int NFCityPlayer::LogicTick()
{
    if (IsNeedSyn())
    {
        SynMapData();
    }

    //UpdateTeam();

    m_oMoveExt.Tick(this);

    m_oViewExt.RefreshGBViewList(this);
    return 0;
}

bool NFCityPlayer::IsCheckPos()
{
    // 传功准备状态的时候，允许客户端把玩家拉到对方身边
    if (m_isPrepare)
        return false;

    return true;
}

int NFCityPlayer::InitRoleInfo(const proto_ff::CityRoleInfo* pRoleInfo)
{
    bool bNeedRefresh = false;
    SynRoleInfo(pRoleInfo, bNeedRefresh);
    m_oMoveExt.InitMapData(&pRoleInfo->map_data());

    m_bIsInit = true;
    m_bEnterSvr = false;

    m_iToken = NFRandInt(1, ONE_MILLION);

    return 0;
}

int NFCityPlayer::SynRoleInfo(const proto_ff::CityRoleInfo* pRoleInfo, bool& bNeedRefreshView)
{
    CHECK_NULL(0, pRoleInfo);
    bNeedRefreshView = false;

    m_stRoleBase.FromPb(pRoleInfo->base());
    if (pRoleInfo->hero().equip_strength_level() != m_stHeroOne.equip_strength_level || m_iTransferID != pRoleInfo->transfer_id())
    {
        bNeedRefreshView = true;
    }
    m_stHeroOne.FromPb(pRoleInfo->hero());

    int iOldTeamNum = m_oTeamExt.GetTeamMemberNum();
    bool bIsLeaderBefore = m_oTeamExt.IsTeamLeader(GetRoleID());
    m_oTeamExt.InitTeamData(&pRoleInfo->team_data());
    bool bIsLeaderAfter = m_oTeamExt.IsTeamLeader(GetRoleID());
    if (bIsLeaderBefore != bIsLeaderAfter || iOldTeamNum != m_oTeamExt.GetTeamMemberNum())
    {
        bNeedRefreshView = true;
    }

    if (pRoleInfo->follow_partner_id() != m_iFollowPartnerID)
    {
        m_iFollowPartnerID = pRoleInfo->follow_partner_id();
        bNeedRefreshView = true;
    }

    if (m_iFollowPartnerID != 0)
    {
        if (m_bFollowPartnerfatigue != pRoleInfo->follow_partner_fatigue())
        {
            m_bFollowPartnerfatigue = pRoleInfo->follow_partner_fatigue();
            bNeedRefreshView = true;
        }

        if (m_iFollowPartnerStar != pRoleInfo->follow_partner_star())
        {
            m_iFollowPartnerStar = pRoleInfo->follow_partner_star();
            bNeedRefreshView = true;
        }
    }

    if (m_iWeaponStrengLv != pRoleInfo->weapon_strengthen_lv())
    {
        m_iWeaponStrengLv = pRoleInfo->weapon_strengthen_lv();
        bNeedRefreshView = true;
    }

    m_ullGuildID = pRoleInfo->guild_id();
    if (pRoleInfo->has_guild_competition())
    {
        m_ullGuildBattleID = pRoleInfo->guild_competition().battle_uid();
    }
    else
    {
        m_ullGuildBattleID = 0uLL;
    }

    if (pRoleInfo->has_dungeon_info())
    {
        m_ullDungeonID = pRoleInfo->dungeon_info().dungeon_id();

        LOGSVR_DEBUG("sync role dungeon id: " << m_ullDungeonID);
    }
    else
    {
        m_ullDungeonID = 0uLL;
    }

    m_ullRaidUUID = pRoleInfo->raid_uuid();

    m_familyCallerID = pRoleInfo->family_info().family_caller_id();
    m_titleID = pRoleInfo->title_id();
    m_titleName = pRoleInfo->title_name();
    m_titleItemID = pRoleInfo->title_item_id();

    m_iTitle2ID = pRoleInfo->title2_id();
    m_transExpRole = pRoleInfo->trans_exp_data().target_id();
    m_isPrepare = pRoleInfo->trans_exp_data().is_prepare();

    m_iTransferID = pRoleInfo->transfer_id();

    for (int i = 0; i < (int)ARRAYSIZE(m_fashions) && i < pRoleInfo->fashions_size(); ++i)
    {
        m_fashions[i] = pRoleInfo->fashions(i);
    }

    m_oQuestExt.InitQuestData(&pRoleInfo->quest_data());

    //battle flag
    if (GetBattleExt()->IsInBattle() != pRoleInfo->in_battle())
    {
        bNeedRefreshView = true;
    }
    GetBattleExt()->SetInBattle(pRoleInfo->in_battle());

    GetBattleExt()->Init(&pRoleInfo->troupe_info());

    GetBuffExt()->Init(&pRoleInfo->buff_info());
    return 0;
}

NFCitySession* NFCityPlayer::GetClientSession()
{
    if (nullptr == m_pClientSession)
    {
        m_pClientSession = NFCitySession::GetObjByGlobalId(m_iClientSessionID);
    }

    return m_pClientSession;
}

int NFCityPlayer::BindClientSession(NFCitySession* pSession)
{
    if (pSession)
    {
        m_pClientSession = pSession;
        m_iClientSessionID = pSession->GetGlobalId();
    }
    else
    {
        m_pClientSession = nullptr;
        m_iClientSessionID = 0;
    }

    return 0;
}

int NFCityPlayer::SynMapData()
{
    proto_ff::Proto_GCMapDataNtf gCMapDataNtf;
    gCMapDataNtf.set_role_id(m_ullRoleID);
    m_oMoveExt.GetMapData()->ToPb(gCMapDataNtf.mutable_map_data());

    NFCityPacketSendUtil::SendMsgToLogicServer(this, E_GC_CITYSVR_MAPDATA_NTF, &gCMapDataNtf);
    m_iCurSynSeq = GetCurSeq();

    return 0;
}

int NFCityPlayer::UpdateMapData(int iMapDescID, const Proto_Vector3& oPos, int iDirection)
{
    m_oMoveExt.UpdateMapData(iMapDescID, oPos, iDirection);
    m_oPlayerEscortAgent.UpdateMapData(this, iMapDescID, oPos, iDirection);

    MarkDirty();
    return 0;
}

int NFCityPlayer::GetAttrValue(proto_ff::AttrType eType) const
{
    return m_stHeroOne.attr_list[eType].value;
}

int NFCityPlayer::MakeFashionData(proto_ff::BattlePlayerHero* pPlayerHero) const
{
    CHECK_NULL(GetRoleID(), pPlayerHero);

    for (int i = 0; i < (int)ARRAYSIZE(m_fashions); ++i)
    {
        pPlayerHero->add_fashion_id(m_fashions[i]);
    }

    return 0;
}

int NFCityPlayer::MakeTransExpRole(proto_ff::RoleTransExpData* pExpData) const
{
    CHECK_NULL(GetRoleID(), pExpData);
    pExpData->set_target_id(m_transExpRole);
    pExpData->set_is_prepare(m_isPrepare);

    return 0;
}

bool NFCityPlayer::HasTask(int iTaskId) const
{
    return m_oQuestExt.HasQuest(iTaskId);
}

bool NFCityPlayer::HasNonFinishTask(int iTaskId) const
{
    return m_oQuestExt.HasNonFinishTask(iTaskId);
}

int NFCityPlayer::OnEnterMap(int iMapInstId, int iMapDescId)
{
    NFCityWorldObject::OnEnterMap(iMapInstId, iMapDescId);

    GetMoveExt()->ClearLastAction();

    return 0;
}
